﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using élénkPróbája.assets;
using élénkPróbája.extentions;
using élénkPróbája.Test.dto;
using élénkPróbája.Test.extention;
using élénkPróbája.validators;

namespace élénkPróbája.Test
{
    [TestClass]
    public class MessagesTester : IDisposable
    {
        public MessagesTester()
        {
            // ensure the resource provider is reset after any tests that use it.
            ValidatorOptions.ResourceProviderType = null;
        }

        public void Dispose()
        {
            ValidatorOptions.ResourceProviderType = null;
        }

//        [TestMethod]
//        public void Correctly_assigns_default_localized_error_message()
//        {
//#if CoreCLR
//			Assert.True(false, "Not implemented on coreclr");
//#else
//            var originalCulture = Thread.CurrentThread.CurrentUICulture;
//            try
//            {
//                var validator = new TestValidator(v => v.RuleFor(x => x.Name).NotEmpty());

//                foreach (var culture in new[] {"en", "de", "fr", "es", "de", "it", "nl", "pl", "pt", "ru", "sv"})
//                {
//                    Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
//                    var message = Messages.ResourceManager.GetString("notnull_error");
//                    var errorMessage = new MessageFormatter().AppendPropertyName("Name").BuildMessage(message);
//                    Debug.WriteLine(errorMessage);
//                    var result = validator.Validate(new Company() {Name = null});
//                    result.Errors.Single().ErrorMessage.ShouldEqual(errorMessage);
//                }
//            }
//            finally
//            {
//                // Always reset the culture.
//                Thread.CurrentThread.CurrentUICulture = originalCulture;
//            }
//#endif
//        }

        [TestMethod]
        public void ResourceProviderType_overrides_default_messagesnote()
        {
            ValidatorOptions.ResourceProviderType = typeof (MyResources);

            var validator = new TestValidator()
            {
                v => v.RuleFor(x => x.Name).NotEmpty()
            };

            var result = validator.Validate(new Company());
            result.Errors.Single().ErrorMessage.ShouldEqual("foo");
        }

        [TestMethod]
        public void Sets_localised_message_via_expression()
        {
            var validator = new TestValidator();
            validator.RuleFor(x => x.Name).NotEmpty().WithLocalizedMessage(() => MyResources.notempty_error);
            var result = validator.Validate(new Company());
            result.Errors.Single().ErrorMessage.ShouldEqual("foo");
        }

        [TestMethod]
        public void When_using_explicitly_localized_message_does_not_fall_back_to_ResourceProvider()
        {
            ValidatorOptions.ResourceProviderType = typeof (MyResources);

            var validator = new TestValidator
            {
                v => v.RuleFor(x => x.Name).NotEmpty().WithLocalizedMessage(() => MyOverridenResources.notempty_error)
            };

            var results = validator.Validate(new Company());
            results.Errors.Single().ErrorMessage.ShouldEqual("bar");
        }

        [TestMethod]
        public void Custom_property_validators_should_respect_ResourceProvider()
        {
            ValidatorOptions.ResourceProviderType = typeof (MyResources);
            var validator = new TestValidator
            {
                v => v.RuleFor(x => x.Name).SetValidator(new MyPropertyValidator())
            };

            var results = validator.Validate(new Company());
            results.Errors.Single().ErrorMessage.ShouldEqual("foo");
        }


        [TestMethod]
        public void When_using_explicitly_localized_message_with_custom_validator_does_not_fall_back_to_ResourceProvider
            ()
        {
            ValidatorOptions.ResourceProviderType = typeof (MyResources);

            var validator = new TestValidator
            {
                v => v.RuleFor(x => x.Name).SetValidator(new MyPropertyValidator())
                    .WithLocalizedMessage(() => MyOverridenResources.notempty_error)
            };

            var results = validator.Validate(new Company());
            results.Errors.Single().ErrorMessage.ShouldEqual("bar");
        }

        [TestMethod]
        public void Can_use_placeholders_with_localized_messages()
        {
            var validator = new TestValidator
            {
                v => v.RuleFor(x => x.Name).NotNull().WithLocalizedMessage(() => TestMessages.PlaceholderMessage, 1)
            };

            var results = validator.Validate(new Company());
            results.Errors.Single().ErrorMessage.ShouldEqual("Test 1");
        }

        [TestMethod]
        public void Can_use_placeholders_with_localized_messages_using_expressions()
        {
            var validator = new TestValidator
            {
                v =>
                    v.RuleFor(x => x.Name).NotNull().WithLocalizedMessage(() => TestMessages.PlaceholderMessage, x => 1)
            };

            var result = validator.Validate(new Company());
            result.Errors.Single().ErrorMessage.ShouldEqual("Test 1");
        }

        [TestMethod]
        public void Setting_global_resource_provider_propogates_to_metadata()
        {
            ValidatorOptions.ResourceProviderType = typeof(TestMessages);
            var validator = new TestValidator();
            validator.RuleFor(x => x.PublicName).NotNull();

            var descriptor = validator.CreateDescriptor();
            var resourceType = descriptor.GetMembersWithValidators().First().First().ErrorMessageSource.ResourceType;

            Assert.AreEqual(typeof (Messages), resourceType); 
        }

        [TestMethod]
        public void Not_Setting_global_resource_provider_uses_default_messages_in_metadata()
        {
            var validator = new TestValidator();
            validator.RuleFor(x => x.Name).NotNull();

            var descriptor = validator.CreateDescriptor();
            var resourceType = descriptor.GetMembersWithValidators().First().First().ErrorMessageSource.ResourceType;

            Assert.AreEqual(typeof (Messages), resourceType);

        }

        private class MyResources
        {
            public static string notempty_error
            {
                get { return "foo"; }
            }
        }

        private class MyOverridenResources
        {
            public static string notempty_error
            {
                get { return "bar"; }
            }
        }

        private class MyPropertyValidator : PropertyValidator
        {
            public MyPropertyValidator() : base(() => MyOverridenResources.notempty_error)
            {

            }

            protected override bool IsValid(PropertyValidatorContext context)
            {
                return false;
            }
        }
    }
}
